package org.test



import org.junit.*

import grails.test.mixin.*

@TestFor(ProductController)
@Mock([Product, PriceAssessment, PriceService])
class ProductControllerTests {

    def populateValidParams(params) {
      params["barcode"] = '123456789'
	  params["description"] = 'A testing Product'
    }

    void testIndex() {
        controller.index()
        assert "/product/list" == response.redirectedUrl
    }

    void testList() {

        def model = controller.list()

        assert model.productInstanceList.size() == 0
        assert model.productInstanceTotal == 0
    }

    void testCreate() {
       def model = controller.create()

       assert model.productInstance != null
    }

    void testSave() {
        controller.save()

        assert model.productInstance != null
        assert view == '/product/create'

        response.reset()

        populateValidParams(params)
        controller.save()

        assert response.redirectedUrl == '/product/show/1'
        assert controller.flash.message != null
        assert Product.count() == 1
    }

    void testShowWithNoProducts() {
        controller.show()

        assert flash.message != null
        assert response.redirectedUrl == '/product/list'
		
		populateValidParams(params)
		def product = new Product(params)
		
		assert product.save() != null
		
		params.id = product.id
		
		def model = controller.show()

		assert model.productInstance['barcode'] == product.barcode
		assert model.productInstance['description'] == product.description

    }
	
	void testShowProductWithPrices() {
		Product product = new Product(barcode: '77777', description: 'A test Product')
		assert product.save(flush: true, validate: false) != null
		
		PriceAssessment price1 = new PriceAssessment(price: 1, product: product)
		assert price1.save(flush: true, validate: false) != null

		PriceAssessment price2 = new PriceAssessment(price: 10, product: product)
		assert price2.save(flush: true, validate: false) != null
		
		product.prices = [price1, price2]
		
		def serviceMock = mockFor(PriceService.class)
		
		serviceMock.demand.getLowestPrice(product) {Product p -> return 1}
		serviceMock.demand.getHighestPrice(product) {Product p -> return 10}
		serviceMock.demand.getAveragePrice(product) {Product p -> return 5.5}
		serviceMock.demand.getIdealPrice(product) {Product p -> return 6.6}
		serviceMock.demand.getNumberOfPrices(product) {Product p -> return 2}
		
		controller.priceService = serviceMock.createMock()
		
		params.id = product.id
		
		def model = controller.show()

		assert model.productInstance['barcode'] == product.barcode
		assert model.productInstance['description'] == product.description
		assert model.productInstance['lowestPrice'] == 1
		assert model.productInstance['highestPrice'] == 10
		
		serviceMock.verify()
	}

    void testEdit() {
        controller.edit()

        assert flash.message != null
        assert response.redirectedUrl == '/product/list'


        populateValidParams(params)
        def product = new Product(params)

        assert product.save() != null

        params.id = product.id

        def model = controller.edit()

        assert model.productInstance == product
    }

    void testUpdate() {
        controller.update()

        assert flash.message != null
        assert response.redirectedUrl == '/product/list'

        response.reset()


        populateValidParams(params)
        def product = new Product(params)

        assert product.save() != null

        // test invalid parameters in update
        params.id = product.id
		params["barcode"] = ''

        controller.update()

        assert view == "/product/edit"
        assert model.productInstance != null

        product.clearErrors()

        populateValidParams(params)
        controller.update()

        assert response.redirectedUrl == "/product/show/$product.id"
        assert flash.message != null

        //test outdated version number
        response.reset()
        product.clearErrors()

        populateValidParams(params)
        params.id = product.id
        params.version = -1
        controller.update()

        assert view == "/product/edit"
        assert model.productInstance != null
        assert model.productInstance.errors.getFieldError('version')
        assert flash.message != null
    }

    void testDelete() {
        controller.delete()
        assert flash.message != null
        assert response.redirectedUrl == '/product/list'

        response.reset()

        populateValidParams(params)
        def product = new Product(params)

        assert product.save() != null
        assert Product.count() == 1

        params.id = product.id

        controller.delete()

        assert Product.count() == 0
        assert Product.get(product.id) == null
        assert response.redirectedUrl == '/product/list'
    }
	
	void testSearch() {
		controller.search()

        assert model.productInstanceList.size() == 0
        assert model.productInstanceTotal == 0

		populateValidParams(params)
		def product = new Product(params)
		assert product.save() != null				
		
		params.searchBarcode = "123456789"
		
		controller.search()

        assert model.productInstanceList.size() == 1
        assert model.productInstanceTotal == 1
	}
	
}
